package com.example.demo.util;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.example.demo.core.BizException;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Maps;
import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.awt.*;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class CaptchaUtils {

    @Value("${captcha.maximum-size:1000}")
    private Long maximumSize;

    @Value("${captcha.expire-after-write:1}")
    private Integer expireAfterWrite;

    @Value("${captcha.concurrency-level:10}")
    private Integer concurrencyLevel;

    private static final int CAPTCHA_WIDTH = 130;// 宽度
    private static final int CAPTCHA_HEIGHT = 48;// 高度
    private static final int CAPTCHA_LENGTH = 4;// 长度
    private static final int CHAR_TYPE_COUNT = 6;// 字符类型个数
    private static final int FONT_TYPE_COUNT = 10;// 字体个数
    private static final int CAPTCHA_TYPE_COUNT = 3;// 验证码类型个数
    private static final int ARITHMETIC_LENGTH = 3; // 算数长度

    private static Cache<String, Object> timedCache;

    @PostConstruct
    public void init() {
        timedCache = CacheBuilder.newBuilder()
                .maximumSize(maximumSize) // 设置缓存的最大容量
                .expireAfterWrite(expireAfterWrite, TimeUnit.MINUTES) // 设置缓存在写入一分钟后失效
                .concurrencyLevel(concurrencyLevel) // 设置并发级别为10
                .recordStats() // 开启缓存统计
                .build();
    }

    public Map<String, String> generate() {
        try {
            Captcha captcha = getRandomCaptcha();
            String verCode = captcha.text().toLowerCase();
            String key = UUID.fastUUID().toString();
            timedCache.put(key, verCode);
            Map<String, String> map = Maps.newHashMap();
            map.put("key", key);
            map.put("image", captcha.toBase64());
            return map;
        } catch (Exception e) {
            throw new BizException("获取验证码失败");
        }
    }

    private Captcha getRandomCaptcha() throws IOException, FontFormatException {
        switch (RandomUtil.randomInt(0, CAPTCHA_TYPE_COUNT)) {
            case 0 -> {
                SpecCaptcha specCaptcha = new SpecCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT, CAPTCHA_LENGTH);
                specCaptcha.setCharType(RandomUtil.randomInt(1, CHAR_TYPE_COUNT + 1));
                specCaptcha.setFont(RandomUtil.randomInt(0, FONT_TYPE_COUNT));
                return specCaptcha;
            }
            case 1 -> {
                GifCaptcha gifCaptcha = new GifCaptcha(CAPTCHA_WIDTH, CAPTCHA_HEIGHT, CAPTCHA_LENGTH);
                gifCaptcha.setCharType(RandomUtil.randomInt(1, CHAR_TYPE_COUNT + 1));
                return gifCaptcha;
            }
            case 2 -> {
                SimpleArithmeticCaptcha simpleArithmeticCaptcha = new SimpleArithmeticCaptcha();
                simpleArithmeticCaptcha.setWidth(CAPTCHA_WIDTH);
                simpleArithmeticCaptcha.setHeight(CAPTCHA_HEIGHT);
                simpleArithmeticCaptcha.setLen(RandomUtil.randomInt(2, ARITHMETIC_LENGTH + 1));
                return simpleArithmeticCaptcha;
            }
        }
        throw new BizException("不支持的验证码类型");
    }

    public static boolean verify(String key, String code) {
        Object verCode = timedCache.getIfPresent(key);
        if (verCode != null && verCode.toString().equalsIgnoreCase(code)) {
            timedCache.invalidate(key);
            return true;
        }
        return false;
    }
}
